package com.example.handler;


import com.example.config.SecurityMemberPO;
import com.example.constant.CrowdConstant;
import com.example.entity.po.MemberPO;
import com.example.entity.vo.MemberVO;
import com.example.service.MemberProviderHandler;
import com.example.service.RedisRemoteService;
import com.example.service.SendEmailService;
import com.example.service.api.MemberService;
import com.example.util.ResultEntity;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

//import org.fall.config.ShortMessageProperties;

@Controller
public class MemberHandler {

    @Autowired
    private RedisRemoteService redisRemoteService;
    @Autowired
    private MemberService memberService;

    @Autowired
    private MemberProviderHandler memberProviderHandler;
    @Autowired
    SendEmailService sendEmailService;

    // 自动注入对象，对象的属性从application.yml文件中获取
//    @Autowired
//    private ShortMessageProperties shortMessageProperties;

    // 发送验证码
    @ResponseBody
    @RequestMapping("/auth/member/send/short/message.json")
    public ResultEntity<String> sendShortMessage(@RequestParam("email") String email){
        System.out.println(email);
        ResultEntity<String> sendResultEntity=sendEmailService.sendSimpleEmail(email,"注册验证码");

        // 判断-发送成功
        if (ResultEntity.SUCCESS.equals(sendResultEntity.getResult())){

            // 得到ResultEntity中的验证码
            String code = sendResultEntity.getData();

            // 将验证码存入到redis中（设置TTL，这里设置为5分钟）
            ResultEntity<String> redisResultEntity = redisRemoteService.setRedisKeyValueWithTimeoutRemote(
                    CrowdConstant.REDIS_CODE_PREFIX + email, code, 5, TimeUnit.MINUTES);

            // 判断存入redis是否成功
            if (ResultEntity.SUCCESS.equals(redisResultEntity.getResult())){
                // 存入成功，返回成功
                return ResultEntity.successWithoutData();
            } else {
                // 存入失败，返回redis返回的ResultEntity
                return redisResultEntity;
            }
        } else {
            // 发送验证码失败，返回发送验证码的ResultEntity
            return sendResultEntity;
        }
    }

    // 进行用户注册操作
    @RequestMapping("/auth/member/do/register.html")
    public String doMemberRegister(MemberVO memberVO, ModelMap modelMap){
        // 获取手机号
        String email = memberVO.getEmail();

        // 拼接为redis存放的key
        String key = CrowdConstant.REDIS_CODE_PREFIX + email;

        // 通过key寻找value（验证码）
        ResultEntity<String> resultEntity = redisRemoteService.getRedisValueByKeyRemote(key);

        String result = resultEntity.getResult();

        // 判断获取redis中的验证码是否成功
        if (ResultEntity.FAILED.equals(result)){
            // 失败，返回主页页面
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getMessage());
            return "reg";
        }

        // 获取redis中的验证码的值
        String redisCode = resultEntity.getData();
        if (redisCode == null){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_NOT_EXIST);
            return "reg";
        }

        // 获取表单提交的验证码
        String formCode = memberVO.getCode();

        // 如果redis中的验证码与表单提交的验证码不同
        if (!Objects.equals(formCode,redisCode)){
            // request域存入不匹配的message
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_INVALID);
            // 返回注册页面
            return "reg";
        }

        // 验证码比对一致，删除redis中的验证码数据
        redisRemoteService.RemoveRedisKeyByKeyRemote(key);

        // 进行注册操作

        // 1、加密
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String formPwd = memberVO.getUserPswd();
        String encode = bCryptPasswordEncoder.encode(formPwd);

        // 2、将加密后的密码放入MemberVO对象
        memberVO.setUserPswd(encode);

        // 3、执行保存
        MemberPO memberPO = new MemberPO();
        BeanUtils.copyProperties(memberVO,memberPO);
        ResultEntity<String> saveResultEntity = memberProviderHandler.saveMemberRemote(memberPO);

        // 4、判断保存是否成功
        String saveResult = saveResultEntity.getResult();
        if (ResultEntity.FAILED.equals(saveResult)){
            // 保存失败，则返回保存操作的ResultEntity中的message，存入request域的message
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, saveResultEntity.getMessage());
            // 回到注册页面
            return "reg";
        }
        System.out.println("全部判断成功");

        // 全部判断成功，跳转到登录页面
        return "/auth/to/member/login/page.html";
    }


    // 登录操作
    @RequestMapping("/login.html")///auth/do/member/login.html
    public String doMemberLogin(
//            @RequestParam("loginAcct") String loginAcct,
//            @RequestParam("loginPswd") String loginPswd,
//            ModelMap modelMap,
//            HttpSession session
    ) {
//        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        SecurityMemberPO user = (SecurityMemberPO) principal;
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        boolean hasUserRole = authentication.getAuthorities().stream()
                .anyMatch(r -> r.getAuthority().equals("ROLE_管理"));
        if(hasUserRole){return "redirect:/admin/page/page.html?pageNum=" + Integer.MAX_VALUE;}
        return "redirect:/";
    }

    // 退出登录
    @RequestMapping("/auth/do/member/logout.html")
    public String doLogout(HttpSession session){
        // 清除session域数据
        session.invalidate();

        // 重定向到首页
        return "/";
    }

    //显示admin的数据
    @RequestMapping("/admin/page/page.html")
    public String getAdminPage(
            // 传入的关键字，若未传入，默认值为一个空字符串（不是null）
            @RequestParam(value = "keyword", defaultValue = "") String keyword,
            // 传入的页码，默认值为1
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            // 传入的页面大小，默认值为5
            @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
            ModelMap modelMap) {
        if(keyword.equals("null")) keyword="";
        //从AdminService中得到对应传参的列表
        PageInfo<MemberPO> pageInfo =memberService.getParseInfo(keyword, pageNum, pageSize);
        //将得到的PageInfo存入modelMap，传给前端
        modelMap.addAttribute(CrowdConstant.NAME_PAGE_INFO, pageInfo);
        //进入对应的显示管理员信息的页面（/WEB-INF/admin-page.jsp）
        return "admin/admin-page";
    }

    @PreAuthorize("hasAuthority('user:delete')")
    @RequestMapping("/admin/page/remove/{adminId}/{pageNum}/{keyword}.html")
    public String removeAdmin(HttpSession session,
                              // 从前端获取的管理员id
                              @PathVariable("adminId") Integer adminId,

                              //@PathVariable("admin.loginAcct") String loginAcct,
                              // 从前端获取的当前页码与关键字（为了删除后跳转的页面仍然是刚才的页面，优化体验）
                              @PathVariable("pageNum") Integer pageNum,
                              @PathVariable("keyword") String keyword) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SecurityMemberPO securityAdmin = (SecurityMemberPO) principal;
        //Admin admin =(Admin)session.getAttribute(CrowdConstant.LOGIN_ADMIN_NAME);
        //if(Objects.equals(loginAcct,admin.getLoginAcct()) )
        //throw new NullPointerException("更新时，不应将账号删除");
        // 调用service层方法，从数据库根据id删除管理员


        memberService.deteid(adminId, securityAdmin.getOriginalAdmin());

        //System.out.println(session.getAttribute(CrowdConstant.LOGIN_ADMIN_NAME));
        //重定向（减少数据库操作）返回信息页
        return "redirect:/admin/page/page.html?pageNum=" + pageNum + "&keyword=" + keyword;
    }


    @PreAuthorize("hasAuthority('user:save')")
    @RequestMapping("/admin/page/doSave.html")
    public String addAdmin(MemberPO memberPO) {

        // 调用service层存储admin对象的方法
        memberService.saveAdmin(memberPO);


        // 重定向会原本的页面，且为了能在添加管理员后看到管理员，设置pageNum为整型的最大值（通过修正到最后一页）
        return "redirect:/admin/page/page.html?pageNum=" + Integer.MAX_VALUE;
    }


    @RequestMapping("/admin/page/update/{adminId}/{pageNum}/{keyword}.html")
    public String toUpdatePage(
            @PathVariable("adminId") Integer adminId,
            @PathVariable("pageNum") Integer pageNum,
            @PathVariable("keyword") String keyword,
            ModelMap modelMap) {
        // 调用Service方法，通过id查询admin对象
        MemberPO admin = memberService.getid(adminId);

        // 将admin对象、页码、关键字存入modelMap，传到前端页面
        modelMap.addAttribute("admin", admin);
        modelMap.addAttribute("pageNum", pageNum);
        modelMap.addAttribute("keyword", keyword);

        // 跳转到更新页面WEB-INF/admin-update.jsp
        return "admin/admin-update";
    }
//    @RequestMapping("/assign/to/page.html?adminId=${admin.id}&pageNum=${requestScope.pageInfo.pageNum}&keyword=${param.keyword}")

    @RequestMapping("/admin/page/doUpdate.html")
    public String updateAdmin(MemberPO admin, @RequestParam("pageNum") Integer pageNum, @RequestParam("keyword") String keyword) {
        System.out.println(admin);
        memberService.updateAdmin(admin);
        return "redirect:/admin/page/page.html?pageNum=" + pageNum + "&keyword=" + keyword;
    }


}
